                .586
                .MMX
                TITLE   BIT LINE 
                .MODEL  FLAT, STDCALL



				EXTRN		CNL_Exp			: BYTE
				EXTRN		CNL_Mant		: DWORD



INTEL_Unpack_Bit_Line_255__NO_SSE	PROTO	C, Io:DWORD, BitL:DWORD, Pool:DWORD, Start:DWORD, N:DWORD, L:DWORD


;====================================================================
;				                                                    
;				M A C R O																
;																	
;====================================================================
;-----------------------------------------------------------------------------------LoadPkBits
LoadPkBits		MACRO	BigExpReturn, ZeroExpReturn
LOCAL	Load16bits, E0, E1, Load32bits, Zero, Start

Start:
		BSR		ECX,Pk_Mant
		JZ		Zero
		XOR		ECX,31
		MOV		EDI,[Pk_Mant_Lo]
		SHLD	Pk_Mant,EDI,CL
		SHL		EDI,CL		
		
		SUB		Pk_Exp,ECX
		ADD		[Counter16bits],ECX
		JGE		Load16bits
		
		MOV		[Pk_Mant_Lo],EDI
	
		CMP		Pk_Exp,0
		JG		BigExpReturn

E1:		MOV		ECX,Pk_Exp
		XOR		Pk_Exp,Pk_Exp
		NEG		ECX
		SHR		Pk_Mant,CL
		JMP		ZeroExpReturn

		ALIGN	16
Load16bits:
		MOV		ECX,[Counter16bits]								
		MOV		[Pk_Mant_Lo],EDI
		CMP		ECX,16
		JGE		Load32bits

		SUB		[Counter16bits],16
		
		MOV		EDI,[PkAdr]		
		SUB		[PkAdr],2
		MOVZX	EDI,WORD PTR [EDI]
		SHL		EDI,CL
		OR		[Pk_Mant_Lo],EDI

		CMP		Pk_Exp,0
		JG		BigExpReturn

E0:		MOV		ECX,Pk_Exp
		XOR		Pk_Exp,Pk_Exp
		NEG		ECX
		SHR		Pk_Mant,CL
		JMP		ZeroExpReturn
				

		ALIGN	16
Load32bits:

		SUB		[Counter16bits],32
		SUB		ECX,16
		CMP		ECX,16
		JGE		Zero
		
		MOV		EDI,[PkAdr]		
		SUB		[PkAdr],4
		MOV		EDI,[EDI-2]
		MOV		[Pk_Mant_Hi],Pk_Mant
		XOR		Pk_Mant,Pk_Mant
		SHLD	Pk_Mant,EDI,CL
		SHL		EDI,CL
		OR		Pk_Mant,[Pk_Mant_Hi]
		OR		[Pk_Mant_Lo],EDI
		
		CMP		Pk_Exp,0
		JG		BigExpReturn
		JMP		E0

		ALIGN	16
Zero:	MOV		Pk_Mant,[Pk_Mant_Lo]

		MOV		ECX,16
		ADD		ECX,[Counter16bits]

		MOV		EDI,[PkAdr]		
		SUB		[PkAdr],4
		MOV		EDI,[EDI-2]
		MOV		[Pk_Mant_Hi],Pk_Mant
		XOR		Pk_Mant,Pk_Mant
		SHLD	Pk_Mant,EDI,CL
		SHL		EDI,CL
		OR		Pk_Mant,[Pk_Mant_Hi]
		MOV		[Pk_Mant_Lo],EDI

		SUB		Pk_Exp,32
		JG		Start
		MOV		ECX,Pk_Exp
		MOV		Pk_Exp,0
		NEG		ECX
		SHR		Pk_Mant,CL
		
		JMP		ZeroExpReturn		

ENDM



;-----------------------------------------------------------------------------------BigExpNewMant
BigExpNewMant	MACRO	BigExpReturn, ZeroExpReturn, CExp_EQ_PkExp

IF		CExp_EQ_PkExp

		SUB		Pk_Mant,[CNL_Mant+NL*4]		

		INC		Position
		SUB		NL,101h

ELSE

		MOVZX	ECX,[CNL_Exp+NL]	
		MOV		EDI,[CNL_Mant+NL*4]		
		
		SUB		ECX,Pk_Exp					;; = -NBits
		MOV		[Pk_Mant_Hi],Pk_Mant
		XOR		Pk_Mant,Pk_Mant
		NEG		ECX							;; = NBits

		SHRD	Pk_Mant,EDI,CL		
		SHR		EDI,CL

		INC		Position
		SUB		NL,101h

		SUB		[Pk_Mant_Lo],Pk_Mant
		MOV		Pk_Mant,[Pk_Mant_Hi]
		SBB		Pk_Mant,EDI
		JS		BigExpReturn


ENDIF

		LoadPkBits	BigExpReturn, ZeroExpReturn

ENDM

;-----------------------------------------------------------------------------------ZeroExpNewMant
ZeroExpNewMant	MACRO	ZeroExpReturn

		SUB		Pk_Mant,[CNL_Mant+NL*4]		

		INC		Position
		SUB		NL,101h
		JMP		ZeroExpReturn


ENDM



;-----------------------------------------------------------------------------------BigExpSet
BigExpSet	MACRO	Z, BigExpReturn, ZeroExpReturn, CExp_EQ_PkExp	
LOCAL	GE64

		CMP		Position,64
		JGE		GE64
		
		MOVD	MM1,Position
		MOVQ	MM2,MM7				; MM7 = 1
		PSLLQ	MM2,MM1	
		PXOR	MM0,MM2

		BigExpNewMant	BigExpReturn, ZeroExpReturn, CExp_EQ_PkExp


		ALIGN	16
GE64:	MOV		ECX,[BLAdr]
		SUB		Position,64
		ADD		[BLAdr],8
		MOVD	MM1,Position
		MOVQ	[ECX],MM0
IF		Z EQ 0
		PXOR	MM0,MM0
ELSE
		PCMPEQB	MM0,MM0
ENDIF			
		CMP		Position,64
		JGE		GE64


IF		Z EQ 0
		MOVQ	MM0,MM7				; MM7 = 1
		PSLLQ	MM0,MM1
ELSE
		MOVQ	MM2,MM7
		PSLLQ	MM2,MM1
		PXOR	MM0,MM2
ENDIF			

		BigExpNewMant	BigExpReturn, ZeroExpReturn, CExp_EQ_PkExp
ENDM
;-----------------------------------------------------------------------------------ZeroExpSet
ZeroExpSet	MACRO	Z, ZeroExpReturn
LOCAL	GE64
	
		CMP		Position,64
		JGE		GE64
		
		MOVD	MM1,Position
		MOVQ	MM2,MM7				; MM7 = 1
		PSLLQ	MM2,MM1	
		PXOR	MM0,MM2

		ZeroExpNewMant	ZeroExpReturn

GE64:	MOV		ECX,[BLAdr]
		SUB		Position,64
		ADD		[BLAdr],8
		MOVD	MM1,Position
		MOVQ	[ECX],MM0
IF		Z EQ 0
		PXOR	MM0,MM0
ELSE
		PCMPEQB	MM0,MM0
ENDIF			
		CMP		Position,64
		JGE		GE64


IF		Z EQ 0
		MOVQ	MM0,MM7				; MM7 = 1
		PSLLQ	MM0,MM1
ELSE
		MOVQ	MM2,MM7
		PSLLQ	MM2,MM1
		PXOR	MM0,MM2
ENDIF			
		ZeroExpNewMant	ZeroExpReturn
ENDM

;-----------------------------------------------------------------------------------BigExp
BigExp	MACRO	Z
LOCAL	ScanExp, ScanMant 

ScanExp:
IRPC	S, <01>
		CMP		[CNL_Exp+NL-S],Pk_Exp_L				;; if CNL_Exp ? Pack Size
		JB		@@SetF_&Z&_&S&						;; if         < -> CNL =ok  
		JE		@@ScanMant_&Z&_&S&					;; if         = -> test Mant
ENDM
		SUB		NL,2
		ADD		Position,2
		JMP		ScanExp



				ALIGN	16
@@SetF_&Z&_1:
		DEC		NL
		INC		Position
@@SetF_&Z&_0:
		BigExpSet	Z, @@BigExp_&Z&, @@ZeroExp_&Z&, 0	;; CExp_EQ_PkExp = false	


				ALIGN	16
ScanMant:
IRPC	S, <01>
		CMP		[CNL_Exp+NL-S],Pk_Exp_L				;; if CNL_Exp ? Pack Size
		JB		@@SetF_&Z&_&S&						;; if         < -> CNL =ok  
@@ScanMant_&Z&_&S&:
		CMP		[CNL_Mant+NL*4-S*4],Pk_Mant			;; if CNL_Mant <= Mant
		JBE		@@SetT_&Z&_&S&						;; -> this CNL Ok
ENDM
		SUB		NL,2
		ADD		Position,2
		JMP		ScanMant





				ALIGN	16
@@SetT_&Z&_1:
		DEC		NL
		INC		Position
@@SetT_&Z&_0:
		BigExpSet	Z, @@BigExp_&Z&, @@ZeroExp_&Z&, 1	;; CExp_EQ_PkExp = true	


ENDM

;-----------------------------------------------------------------------------------ZeroExp
ZeroExp	MACRO	Z
LOCAL	TE, ScanMant 

		CMP		Pk_Mant,0
		JE		@@Exit_&Z&

		CMP		BYTE PTR [CNL_Exp+NL],0
		JE		ScanMant
TE:		DEC		NL
		INC		Position
		CMP		BYTE PTR [CNL_Exp+NL],0
		JNE		TE
				

ScanMant:
IRPC	S, <0123>
		CMP		[CNL_Mant+NL*4-S*4],Pk_Mant
		JB		@@ZeroInvert_or_Set_&Z&_&S&
		JE		@@Set_Exit_&Z&_&S&	
ENDM
		SUB		NL,4
		ADD		Position,4
		JMP		ScanMant


				ALIGN	16
IRPC	S, <0123>
@@ZeroInvert_or_Set_&Z&_&S&:
IF		S
		SUB		NL,S
		ADD		Position,S
ENDIF
		
		ZeroExpSet	Z, ScanMant 
ENDM


				ALIGN	16
IRPC	S, <0123>
@@Set_Exit_&Z&_&S&:
IF		S
		SUB		NL,S
		ADD		Position,S
ENDIF
		ZeroExpSet	Z, @@Exit_&Z& 
ENDM



ENDM


;-----------------------------------------------------------------------------------Exit
Exit	MACRO	Z
LOCAL	E0, E1, E2, E3, Exit

		MOVZX	EBX,AL						; L-1-P
		MOVZX	EAX,AH						; new N

		LEA		EBX,[Position+EBX+1]		; end of BL   (Io+L)
		SUB		EAX,EBX
		NEG		EAX							; position last !Z bits 
		MOV		EDI,[BLAdr]


		CMP		EBX,64
		JGE		E0

		MOVD	MM1,EAX
		MOVD	MM3,EBX
		PCMPEQB	MM2,MM2
		PCMPEQB	MM4,MM4
		PCMPEQB	MM6,MM6
		PSLLQ	MM2,MM1
		MOVQ	MM5,[EDI]
		PSLLQ	MM4,MM3
		PXOR	MM6,MM4
		PXOR	MM0,MM2						; set/reset last !Z bits		
		PAND	MM5,MM4
		PAND	MM0,MM6
		POR		MM0,MM5
		MOVQ	[EDI],MM0
		JMP		Exit


E0:		CMP		EAX,64
		JGE		E3

		MOVD	MM1,EAX
		PCMPEQB	MM2,MM2
		PSLLQ	MM2,MM1
		PXOR	MM0,MM2						; set/reset last !Z bits		
		MOVQ	[EDI],MM0
IF		Z
		PXOR	MM0,MM0
ELSE	
		PCMPEQB	MM0,MM0
ENDIF
E1:		ADD		EDI,8
		SUB		EBX,64
		CMP		EBX,64
		JL		E2				
		MOVQ	[EDI],MM0
		JMP		E1

E2:		MOVD	MM3,EBX
		PCMPEQB	MM4,MM4
		PCMPEQB	MM6,MM6
		MOVQ	MM5,[EDI]
		PSLLQ	MM4,MM3
		PXOR	MM6,MM4
		PAND	MM5,MM4
		PAND	MM0,MM6
		POR		MM0,MM5
		MOVQ	[EDI],MM0
		JMP		Exit

E3:		MOVQ	[EDI],MM0
		ADD		EDI,8
IF		Z
		PCMPEQB	MM0,MM0
ELSE
		PXOR	MM0,MM0
ENDIF
		SUB		EAX,64
		SUB		EBX,64
		JMP		E0
		
Exit:		
ENDM


;-----------------------------------------------------------------------------------TestHiBit
TestHiBit	MACRO	Z
LOCAL	L1, L2, L3, L4, L5, L6
		
IF		Z
		MOV		NL,[L]
		SUB		NL,[N]
ELSE
		MOV		NL,[N]
ENDIF

		SHL		NL,8
		MOV		AL,BYTE PTR [L]

		MOVZX	ECX,BYTE PTR [CNL_Exp+NL]
		MOV		EDI,[CNL_Mant+NL*4]
		
		LEA		Pk_Exp,[32+ECX]
		CMP		ECX,0
		JNE		L1
		DEC		EDI
		BSR		ECX,EDI
		LEA		Pk_Exp,[ECX+1]
		XOR		ECX,31
		SHL		EDI,CL
L1:

		MOV		Position,[Start]
		ADD		[Position],Pk_Exp

		MOV		Position,[Position]
		DEC		Position						; HiBit Position
		MOV		ECX,Position
		SHR		Position,3
		ADD		Position,[Pool]
		SUB		Position,7+2
		MOV		[PkAdr],Position

		MOVQ	MM0,[Position+2]
		AND		ECX,7
		XOR		ECX,7

		MOV		[Counter16bits],ECX
		SUB		[Counter16bits],16

		MOVD	MM1,ECX
		PSLLQ	MM0,MM1
		MOVQ	QWORD PTR [Pk_Mant_Lo],MM0

		MOV		Pk_Mant,[Pk_Mant_Hi]

		CMP		Pk_Exp,32
		JGE		L6
		MOV		ECX,32
		SUB		ECX,Pk_Exp
		SHR		Pk_Mant,CL
		SHL		Pk_Mant,CL
L6:

		OR		Pk_Mant,1 shl 31
		CMP		Pk_Mant,EDI
		JA		L2

		MOV		Pk_Mant,[Pk_Mant_Hi]		; restore HiBit
		JMP		L3

L2:		XOR		Pk_Mant,1 shl 31			; delete HiBit
		MOV		Position,[Start]
		DEC		DWORD PTR [Position]

L3:		SUB		Pk_Exp,32
		JG		L4
		MOV		ECX,Pk_Exp
		MOV		Pk_Exp,0
		NEG		ECX
		SHR		Pk_Mant,CL
		JMP		L5

L4:		CMP		Pk_Mant,0
		JL		L5

		LoadPkBits L5, L5

L5:		DEC		NL

ENDM



;====================================================================
;
;				D A T A
;
;====================================================================
				.DATA
				ALIGN	8

One				DQ		1					; const



;====================================================================
;
;				C O D E
;
;====================================================================
				.CODE

INTEL_Unpack_Bit_Line_255__NO_SSE	PROC	C, Io:DWORD, BitL:DWORD, Pool:DWORD, Start:DWORD, N:DWORD, L:DWORD
	

				NL			EQU	EAX
				Pk_Exp		EQU	EBX
				Pk_Exp_L	EQU	BL
				Pk_Mant		EQU	EDX
				Position	EQU	ESI
		

		PUSHAD




;________________LOCAL VARIABLES__________________________________________________________
				NLocals = 6
		SUB		ESP,4*NLocals								; WARNING!!!!!!! 
				BLAdr			EQU DWORD PTR [ESP]			; 
				PkAdr			EQU DWORD PTR [ESP+4]		; DONT USE PUSH-POP-CALL
				Counter16bits	EQU DWORD PTR [ESP+4*2]		
				Pk_Mant_Lo		EQU DWORD PTR [ESP+4*3]
				Pk_Mant_Hi		EQU DWORD PTR [ESP+4*4]
				More0s			EQU BYTE  PTR [ESP+4*5]
;_____________________________________________________________________________________
				

		MOV		EAX,[L]
		SHR		EAX,1
		CMP		[N],EAX
		SETLE	[More0s]			
		

		CMP		[More0s],0
		JE		@@1
		TestHiBit	0
		JMP		@@2
@@1:	TestHiBit	1			
@@2:		




		MOVQ	MM7,[One]	

		MOV		ECX,[BitL]				; Bit Line address
		MOV		Position,[Io]			; start index 
		SHR		Position,3					
		LEA		ECX,[ECX+Position]
		MOVQ	MM0,[ECX]				; load first 8 bytes
		MOV		[BLAdr],ECX				; save address  
		MOV		Position,[Io]
		AND		Position,7
		MOVD	MM1,Position
		PCMPEQB	MM2,MM2					
		PSLLQ	MM2,MM1
		POR		MM0,MM2					; set bits if N>(L/2)
		CMP		[More0s],0
		JE		@@5
		PXOR	MM0,MM2					; clean bits if N<=(L/2)
@@5:
		



		CMP		[More0s],0
		JE		@@10
		
		CMP		Pk_Exp,0
		JNE		@@BigExp_0
		JMP		@@ZeroExp_0
							
@@10:

		CMP		Pk_Exp,0
		JNE		@@BigExp_1
		JMP		@@ZeroExp_1


				ALIGN	16
@@BigExp_0:
		BigExp	0


				ALIGN	16
@@BigExp_1:
		BigExp	1


				ALIGN	16
@@ZeroExp_0:	
		ZeroExp	0

		
				ALIGN	16
@@ZeroExp_1:	
		ZeroExp	1


				ALIGN	16
@@Exit_0:
		Exit	0
		
		ADD		ESP,4*NLocals										
		POPAD
		EMMS
		RET		

				ALIGN	16
@@Exit_1:
		Exit	1
		ADD		ESP,4*NLocals										
		POPAD
		EMMS
		RET		
					
INTEL_Unpack_Bit_Line_255__NO_SSE	ENDP
END